package com.dycloud.project.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.dycloud.project.constant.CacheConstants;
import com.dycloud.project.constant.Constants;
import com.dycloud.project.domain.SysUser;
import com.dycloud.project.enums.ReviewStatusEnum;
import com.dycloud.project.exception.ServiceException;
import com.dycloud.project.request.ReviewIndustryRequest;
import com.dycloud.project.service.ISysUserService;
import com.dycloud.project.utils.DateUtils;
import com.dycloud.project.utils.SecurityUtils;
import com.dycloud.project.security.LoginUser;
import com.dycloud.project.domain.IndustryTrends;
import com.dycloud.project.mapper.IndustryTrendsMapper;
import com.dycloud.project.service.IIndustryTrendsService;
import com.dycloud.project.vo.IndustryTrendsPageVO;
import com.dycloud.project.vo.PushTrendItemVo;
import com.dycloud.project.vo.UserIndustryTrendsVO;
import com.dycloud.project.web.page.TableDataInfo;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author : renhang
 * @description IndustryTrendsServiceImpl
 * @date : 2025-07-02 18:40
 **/
@Service("iIndustryTrendsService")
@Slf4j
public class IndustryTrendsServiceImpl implements IIndustryTrendsService {

    @Autowired
    private IndustryTrendsMapper industryTrendsMapper;

    @Autowired
    RedissonClient redissonClient;


    @Autowired
    private ISysUserService sysUserService;

    /**
     * 查询行业动态新闻
     *
     * @param id 行业动态新闻主键
     * @return 行业动态新闻
     */
    @Override
    public UserIndustryTrendsVO selectIndustryTrendsById(Long id) {
        IndustryTrends industryTrends = industryTrendsMapper.selectIndustryTrendsById(id);
        UserIndustryTrendsVO vo = BeanUtil.copyProperties(industryTrends, UserIndustryTrendsVO.class);
        vo.setNickName(sysUserService.selectUserById(vo.getPublishId()).getNickName());
        vo.setAuditorName(sysUserService.selectUserById(vo.getAuditorId()).getNickName());
        return vo;
    }

    /**
     * 查询行业动态新闻列表
     *
     * @param industryTrends 行业动态新闻
     * @return 行业动态新闻
     */
    @Override
    public TableDataInfo selectIndustryTrendsList(IndustryTrends industryTrends) {
        // 租户隔离,admin可以看所有的
        LoginUser loginUser = SecurityUtils.getLoginUser();
        if (SecurityUtils.isCommonUser()) {
            industryTrends.setPublishId(loginUser.getUserId());
        }
        List<IndustryTrends> trends = industryTrendsMapper.selectIndustryTrendsList(industryTrends);
        if (CollUtil.isEmpty(trends)) {
            return TableDataInfo.build(trends, trends);
        }

        Set<Long> auditorIds = trends.stream().map(IndustryTrends::getAuditorId).collect(Collectors.toSet());
        auditorIds.addAll(trends.stream().map(IndustryTrends::getPublishId).collect(Collectors.toSet()));
        Map<Long, SysUser> sysUserMap = sysUserService.getUserInfoMap(auditorIds);

        List<IndustryTrendsPageVO> vos = trends.stream().map(trend -> {
            IndustryTrendsPageVO vo = BeanUtil.copyProperties(trend, IndustryTrendsPageVO.class);
            if (Objects.nonNull(trend.getAuditorId())) {
                vo.setAuditorId(trend.getAuditorId());
                vo.setAuditorName(sysUserMap.get(trend.getAuditorId()).getNickName());
                vo.setNickName(sysUserMap.get(trend.getPublishId()).getNickName());
            }
            return vo;
        }).toList();

        return TableDataInfo.build(vos, trends);
    }

    /**
     * 新增行业动态新闻
     *
     * @param industryTrends 行业动态新闻
     * @return 结果
     */
    @Override
    public int insertIndustryTrends(IndustryTrends industryTrends) {
        // 管理员创建的不需要审核
        if (SecurityUtils.isAdmin(SecurityUtils.getUserId())) {
            industryTrends.setStatus(ReviewStatusEnum.PUBLISHED.getCode());
            industryTrends.setAuditorId(SecurityUtils.getUserId());
            industryTrends.setAuditTime(DateUtils.getNowDate());
        }
        industryTrends.setPublishId(SecurityUtils.getUserId());
        industryTrends.setCreateTime(DateUtils.getNowDate());
        industryTrends.setUpdateTime(DateUtils.getNowDate());
        return industryTrendsMapper.insertIndustryTrends(industryTrends);
    }

    /**
     * 修改行业动态新闻
     *
     * @param industryTrends 行业动态新闻
     * @return 结果
     */
    @Override
    public int updateIndustryTrends(IndustryTrends industryTrends) {
        checkIsReview(industryTrends.getId());
        industryTrends.setUpdateTime(DateUtils.getNowDate());
        return industryTrendsMapper.updateIndustryTrends(industryTrends);
    }

    /**
     * 批量删除行业动态新闻
     *
     * @param ids 需要删除的行业动态新闻主键
     * @return 结果
     */
    @Override
    public int deleteIndustryTrendsByIds(Long[] ids) {
        for (Long id : ids) {
            checkIsReview(id);
        }
        return industryTrendsMapper.deleteIndustryTrendsByIds(ids);
    }

    /**
     * 删除行业动态新闻信息
     *
     * @param id 行业动态新闻主键
     * @return 结果
     */
    @Override
    public int deleteIndustryTrendsById(Long id) {
        return industryTrendsMapper.deleteIndustryTrendsById(id);
    }

    @Override
    public void review(ReviewIndustryRequest request) {
        request.getIds().forEach(id -> {
            IndustryTrends industryTrends = industryTrendsMapper.selectIndustryTrendsById(id);
            if (Objects.isNull(industryTrends)) {
                throw new RuntimeException("id:" + id + "的行业动态不存在");
            }
        });

        List<IndustryTrends> list = request.getIds().stream().map(e -> {
            IndustryTrends trends = new IndustryTrends();
            trends.setId(e);
            trends.setAuditorId(SecurityUtils.getUserId());
            trends.setStatus(request.getStatus());
            trends.setAuditRemark(request.getAuditRemark());
            trends.setUpdateTime(DateUtils.getNowDate());
            trends.setAuditTime(DateUtils.getNowDate());
            return trends;
        }).toList();

        industryTrendsMapper.updateIndustryTrendsList(list);
    }

    @Override
    public void view(Long id) {
        RLock lock = redissonClient.getLock(String.format(CacheConstants.INSERT_INDUSTRY_LOCK_KEY, id));
        try {
            // 尝试加锁3秒
            boolean isLocked = lock.tryLock(3, TimeUnit.SECONDS);
            if (isLocked) {
                IndustryTrends industryTrends = industryTrendsMapper.selectIndustryTrendsById(id);
                if (Objects.isNull(industryTrends)) {
                    throw new RuntimeException("行业动态不存在");
                }

                IndustryTrends trends = new IndustryTrends();
                trends.setId(id);
                trends.setViewCount(industryTrends.getViewCount() + 1);
                industryTrendsMapper.updateIndustryTrends(trends);
            } else {
                // 获取锁失败
                log.warn("未能获取锁，跳过此次浏览统计");
            }
        } catch (InterruptedException e) {
            log.warn("view Warn! tryLock fail");
        } finally {
            if (lock.isLocked() && lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }

    }


    private void checkIsReview(Long id) {
        IndustryTrends industryTrends = industryTrendsMapper.selectIndustryTrendsById(id);
        if (Objects.isNull(industryTrends)) {
            throw new ServiceException("行业动态不存在");
        }
        if (Objects.equals(industryTrends.getIsDel(), Constants.ONE)) {
            throw new ServiceException("行业动态已删除");
        }
        if (Objects.equals(industryTrends.getStatus(), Constants.ONE)) {
            throw new ServiceException("已经发布的行业动态不能修改");
        }
    }

    @Override
    public int selectCount(Long userId) {
        return industryTrendsMapper.selectCount(userId);
    }

    @Override
    public List<PushTrendItemVo> selectPushTrend(Long userId) {
        return industryTrendsMapper.selectPushTrend(userId);
    }
}
